import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * The Class VendingMachineTest; used to test the VendingMachine class.
 * 
 * @author Odessa
 */

public class VendingMachineTest
{

	VendingMachine myVendingMachine;
	VendingMachineItem kitkat;



	/**
	 * Sets up the test fixture.
	 * 
	 * @throws Exception the exception
	 */
	@Before
	public void setUp() throws Exception
	{
		myVendingMachine = new VendingMachine();
		kitkat = new VendingMachineItem("kitkat", 1.00);
	}



	/**
	 * Tear down.
	 * 
	 * @throws Exception the exception
	 */
	@After
	public void tearDown() throws Exception
	{
		myVendingMachine = null;
	}



	/**
	 * Test method for
	 * {@link VendingMachine#addItem(VendingMachineItem, java.lang.String)}.
	 * Tests adding an item to the vending machine in an empty slot.
	 */
	@Test
	public void testAddItem_EmptySlot()
	{
		VendingMachineItem doritos = new VendingMachineItem("doritos", 1.25);
		VendingMachineItem coke = new VendingMachineItem("coke", 1.50);
		
		myVendingMachine.addItem(kitkat, myVendingMachine.A_CODE);
		myVendingMachine.addItem(doritos, myVendingMachine.B_CODE);
		myVendingMachine.addItem(coke, myVendingMachine.C_CODE);
		myVendingMachine.addItem(coke, myVendingMachine.D_CODE);

		assertEquals(kitkat, myVendingMachine.getItem(myVendingMachine.A_CODE));
		assertEquals(doritos, myVendingMachine.getItem(myVendingMachine.B_CODE));
		assertEquals(coke, myVendingMachine.getItem(myVendingMachine.C_CODE));
		assertEquals(coke, myVendingMachine.getItem(myVendingMachine.D_CODE));
	}



	/**
	 * Test method for
	 * {@link VendingMachine#addItem(VendingMachineItem, java.lang.String)}.
	 * Tests adding an item to the vending machine in a slot that is already
	 * occupied.
	 */
	@Test(expected = VendingMachineException.class)
	public void testAddItem_NonemptySlot()
	{
		VendingMachineItem doritos = new VendingMachineItem("doritos", 1.25);

		myVendingMachine.addItem(kitkat, myVendingMachine.A_CODE);
		myVendingMachine.addItem(doritos, myVendingMachine.A_CODE);
	}



	/**
	 * Test method for
	 * {@link VendingMachine#addItem(VendingMachineItem, java.lang.String)}.
	 * Tests adding an item with an invalid code to the vending machine.
	 */
	@Test(expected = VendingMachineException.class)
	public void testAddItem_InvalidCode()
	{
		myVendingMachine.addItem(kitkat, "E");
	}



	/**
	 * Test method for {@link VendingMachine#removeItem(java.lang.String)}.
	 * Tests removing an item from the vending machine when the slot is not
	 * empty.
	 */
	@Test
	public void testRemoveItem_NonemptySlot()
	{
		myVendingMachine.addItem(kitkat, myVendingMachine.A_CODE);

		assertEquals(kitkat,
				myVendingMachine.removeItem(myVendingMachine.A_CODE));
	}



	/**
	 * Test method for {@link VendingMachine#removeItem(java.lang.String)}.
	 * Tests removing an item from an empty slot in the vending machine.
	 */
	@Test(expected = VendingMachineException.class)
	public void testRemoveItem_EmptySlot()
	{
		myVendingMachine.removeItem(myVendingMachine.A_CODE);
	}



	/**
	 * Test method for {@link VendingMachine#removeItem(java.lang.String)}.
	 * Tests removing an item from an invalid slot in the vending machine.
	 */
	@Test(expected = VendingMachineException.class)
	public void testRemoveItem_InvalidCode()
	{
		myVendingMachine.removeItem("E");
	}



	/**
	 * Test method for {@link VendingMachine#insertMoney(double)}. Tests the
	 * insertMoney method when the amount entered < zero.
	 */
	@Test(expected = VendingMachineException.class)
	public void testInsertMoney_LessThanZero()
	{
		myVendingMachine.insertMoney(-1);
	}



	/**
	 * Test method for {@link VendingMachine#insertMoney(double)}. Tests the
	 * insertMoney method when the amount entered >= zero.
	 */
	@Test
	public void testInsertMoney_GreaterThanZero()
	{
		myVendingMachine.insertMoney(1);

		assertEquals(1, myVendingMachine.getBalance(), 0.001);
	}



	/**
	 * Test method for {@link VendingMachine#getBalance()}. Tests the getBalance
	 * method to ensure that the vending machine starts with a 0 balance.
	 */
	@Test
	public void testGetBalance()
	{
		assertEquals(0, myVendingMachine.getBalance(), 0.001);
	}



	/**
	 * Test method for {@link VendingMachine#makePurchase(java.lang.String)}.
	 * Tests the makePurchase method if there is enough money to make a
	 * purchase.
	 */
	@Test
	public void testMakePurchase_EnoughMoney()
	{
		myVendingMachine.addItem(kitkat, myVendingMachine.A_CODE);
		myVendingMachine.insertMoney(5);

		assertTrue(myVendingMachine.makePurchase(myVendingMachine.A_CODE));
		assertEquals(4, myVendingMachine.getBalance(), 0.001);
	}



	/**
	 * Test method for {@link VendingMachine#makePurchase(java.lang.String)}.
	 * Tests the makePurchase method if there isn't enough money put into the
	 * vending machine to make a purchase.
	 */
	@Test
	public void testMakePurchase_NotEnoughMoney()
	{
		myVendingMachine.addItem(kitkat, myVendingMachine.A_CODE);

		assertFalse(myVendingMachine.makePurchase(myVendingMachine.A_CODE));
	}



	/**
	 * Test method for {@link VendingMachine#makePurchase(java.lang.String)}.
	 * Tests the makePurchase method if a purchase is made for an empty slot.
	 */
	@Test
	public void testMakePurchase_EmptySlot()
	{
		assertFalse(myVendingMachine.makePurchase(myVendingMachine.A_CODE));
	}



	/**
	 * Test method for {@link VendingMachine#returnChange()}.
	 */
	@Test
	public void testReturnChange()
	{
		myVendingMachine.addItem(kitkat, myVendingMachine.A_CODE);
		myVendingMachine.insertMoney(5);
		myVendingMachine.makePurchase(myVendingMachine.A_CODE);

		assertEquals(4, myVendingMachine.returnChange(), 0.001);
		assertEquals(0, myVendingMachine.getBalance(), 0.001);
	}

}
